package com.ebupt.migu.music.common.util;

import com.ebupt.migu.music.common.exception.MyException;
import com.ebupt.migu.music.common.exception.StatusEnum;
import com.opencsv.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Intellij IDEA.
 * User:  liuyangyang@cd.ebupt.com
 * Date:  2019/9/9
 */
@Slf4j
public class CSVUtils {

    public static final String ENCODE = "GBK";

    /**
     * 根据文件路径读取文件内容
     *
     * @param path 文件路径
     * @return
     */
    public static List<String[]> csvRead(String path) {
        return csvRead(path,ENCODE);
    }

    public static List<String[]> csvRead(String path,String code) {
        List<String[]> records = new ArrayList<>();
        InputStreamReader inputStreamReader = null;
        CSVReader csvReader = null;
        try {
            inputStreamReader = new InputStreamReader(new FileInputStream(path), Charset.forName(code));
            CSVParser csvParser = new CSVParserBuilder().build();
            csvReader = new CSVReaderBuilder(inputStreamReader).withCSVParser(csvParser).build();
            records = csvReader.readAll();
            csvReader.close();
            return records;
        } catch (Exception e) {
            log.error("读取CSV文件出错", e);
        } finally {
            closeIN(inputStreamReader, csvReader);
        }
        return records;
    }

    /**
     * 根据文件路径读取文件内容
     *
     * @param separator 分割符
     * @param path      文件路径
     * @return
     */
    public static List<String[]> csvRead(String path, char separator) {
        List<String[]> records = new ArrayList<>();
        InputStreamReader inputStreamReader = null;
        CSVReader csvReader = null;
        try {
            inputStreamReader = new InputStreamReader(new FileInputStream(path), Charset.forName(ENCODE));
            CSVParser csvParser = new CSVParserBuilder().withSeparator(separator).build();
            csvReader = new CSVReaderBuilder(inputStreamReader).withCSVParser(csvParser).build();
            records = csvReader.readAll();
            return records;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("读取CSV文件出错", e);
            throw new MyException(StatusEnum.ERROR,e.getMessage());
        } finally {
            closeIN(inputStreamReader, csvReader);
        }
    }

    /**
     * 读取文件内容
     *
     * @param fileToUpload 文件
     * @return
     */
    public static List<String[]> csvRead(MultipartFile fileToUpload) {
        List<String[]> records = new ArrayList<>();
        InputStreamReader inputStreamReader = null;
        CSVReader csvReader = null;
        try {
            InputStream inputStream = fileToUpload.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream, Charset.forName(ENCODE));
            CSVParser csvParser = new CSVParserBuilder().build();
            csvReader = new CSVReaderBuilder(inputStreamReader).withCSVParser(csvParser).build();
            records = csvReader.readAll();
            csvReader.close();
            return records;
        } catch (Exception e) {
            log.error("读取CSV文件出错", e);
        } finally {
            closeIN(inputStreamReader, csvReader);
        }
        return records;
    }

    /**
     * 将数据写入CSV文件
     *
     * @param path     文件保存路径
     * @param fileName 文件名
     * @param data     数据集
     */
    public static void csvWrite(String path, String fileName, List<String[]> data) {
        CSVWriter csvWriter = null;
        try {
            String csvName = path + fileName + ".csv";
            // 创建文件所在目录
            File file = new File(FilenameUtils.getFullPath(csvName));
            if (!file.exists()) {
                file.mkdirs();
            }
            csvWriter = new CSVWriter(new OutputStreamWriter(new FileOutputStream(csvName), StandardCharsets.UTF_8.name()), ';', CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);
            csvWriter.writeAll(data);
        } catch (Exception e) {
            log.error("将数据写入CSV出错", e);
        } finally {
            if (null != csvWriter) {
                try {
                    csvWriter.flush();
                    csvWriter.close();
                } catch (IOException e) {
                    log.error("关闭文件输出流出错", e);
                }
            }
        }
    }

    /**
     * 判断上传文件是否为空，是否符合类型
     *
     * @param fileToUpload
     * @param suffix       文件类型参数
     * @return
     */
    public static boolean validateUploadFile(MultipartFile fileToUpload, String... suffix) {

        if (fileToUpload.getSize() == 0) {
            return false;
        }
        if (suffix.length == 0) {
            return false;
        }
        String fileName = fileToUpload.getOriginalFilename();
        if (StringUtils.isNotBlank(fileName) && fileName.contains("\\")) {
            fileName = StringUtils.substringAfterLast(fileName, "\\");
        }
        return FilenameUtils.isExtension(fileName, suffix);

    }

    /**
     * 关闭读入文件流
     *
     * @param inputStreamReader
     * @param csvReader
     */
    private static void closeIN(InputStreamReader inputStreamReader, CSVReader csvReader) {
        if (csvReader != null) {
            try {
                csvReader.close();
            } catch (Exception e) {
                log.error("关闭文件读入流出错", e);
            }
        }
        if (inputStreamReader != null) {
            try {
                inputStreamReader.close();
            } catch (Exception e) {
                log.error("关闭文件读入流出错", e);
            }
        }
    }

    /**
     * 上传附件到指定目录
     *
     * @param appfile
     * @param newPath
     */
    public static void upload(MultipartFile appfile, String newPath) {
        File file = new File(newPath);
        try {
            appfile.transferTo(file);
        } catch (IllegalStateException e) {
            log.error("上传文件出错：" + appfile.getOriginalFilename(), e);
        } catch (IOException e) {
            log.error("上传文件出错：" + appfile.getOriginalFilename(), e);
        }
    }
}
